home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / pccts.zip / begtut.txt < prev    next >
Text File  |  1992-12-08  |  35KB  |  1,427 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.                         Introductory Tutorial
  8.  
  9.  
  10.                               PCCTS 1.0x
  11.  
  12.  
  13.                  Terence Parr, Hank Dietz, Will Cohen
  14.  
  15.                    School of Electrical Engineering
  16.                           Purdue University
  17.                       West Lafayette, IN  47907
  18.                               Fall 1992
  19.  
  20.                          parrt@ecn.purdue.edu
  21.                          hankd@ecn.purdue.edu
  22.                         cohenw@ecn.purdue.edu
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.      The Purdue Compiler-Construction Tool Set (PCCTS) is  a  set
  31.      of  public  domain software tools designed to facilitate the
  32.      implementation of compilers and other  translation  systems.
  33.      In  many  ways, PCCTS is similar to a highly integrated ver-
  34.      sion of YACC and LEX; where ANTLR (ANother Tool for Language
  35.      Recognition)  corresponds to YACC and DLG (DFA-based Lexical
  36.      analyzer Generator) functions like LEX.  However, PCCTS  has
  37.      many  additional  features which make it easier to use for a
  38.      wide range of translation problems.
  39.  
  40.      This document introduces the basic functionality of PCCTS by
  41.      example.   The user need not be familiar with parsing theory
  42.      or other compiler tools, but  any  familiarity  reduces  the
  43.      learning curve substantially.  The PCCTS reference manual is
  44.      a necessary supplement to this tutorial as information  here
  45.      regarding PCCTS structures and operation is incomplete.
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.                                                                 Page 1
  62.  
  63. PCCTS Introductory Tutorial 1.0x
  64.  
  65.  
  66. 1.  Introduction
  67.  
  68.      PCCTS allows the user to  describe  languages  (e.g.  programming
  69. language,  OS  shell, game, editor); from such a description, a C pro-
  70. gram is generated that recognizes and, optionally, translates  phrases
  71. in that language.  The user must specify the following:
  72.  
  73. (i)  How the input stream is to be broken  up  into  lexemes  (tokens)
  74.      which comprise the vocabulary of the language.
  75.  
  76. (ii) How the tokens are to be grouped; i.e. what structure/grammar  is
  77.      to be applied to the token stream.
  78.  
  79. (iii)C actions which perform a user-specified translation.  Along with
  80.      this   specification,   the   user   must   also  describe  token
  81.      attributes-objects that actions use to communicate with the lexi-
  82.      cal analysis phase of translation.
  83.  
  84. Similarly, this  tutorial  is  broken  up  into  sections  on  lexical
  85. analysis, syntactic analysis, and actions/translation.
  86.  
  87. 2.  Lexical Analysis
  88.  
  89.      Before understanding a phrase in English, one must  separate  the
  90. stream  of  characters  into  a  stream  of  words;  e.g.  the phrase:
  91. "thisisveryhardtoread" accentuates this fact-recognition cannot easily
  92. be done from a character stream, only from word/token streams.
  93.  
  94.      Compilers and  other  translators  are  very  strict  about  this
  95. "tokenization"  and generally describe tokens via regular expressions-
  96. expressions that describe sets of character  sequences.   The  regular
  97. expressions are, in fact, language descriptions as well.  For example,
  98. hello is a regular expression that recognizes a sequence of five char-
  99. acters; namely, the word: "hello".  To inform PCCTS that "hello" is to
  100. be a word in the vocabulary of your language, the  following  descrip-
  101. tion would be placed in your grammar file.
  102.  
  103.  
  104. #token LABEL "hello"
  105.  
  106.  
  107.  
  108. where LABEL is some label (C #define) that you  want  associated  with
  109. that  token.  To test regular expressions in PCCTS, let us form a sim-
  110. ple, complete description which recognizes "hello" (we will  use  this
  111. description as a base for all examples in this section):
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.                                                                 Page 2
  124.  
  125. PCCTS Introductory Tutorial 1.0x
  126.  
  127.  
  128.  
  129. #header <<#include "charbuf.h">>
  130.  
  131. <<main() { ANTLR(a(), stdin); }>>
  132.  
  133. #token WORD "hello"
  134.  
  135. a : WORD ;
  136.  
  137.  
  138.  
  139. This is a minimal description in that it  contains  everything  needed
  140. for PCCTS to generate an executable (actually, to generate all C files
  141. needed for the C compiler to generate  an  executable).   The  #header
  142. <<...>>  instruction  informs PCCTS that the C code inside the <<...>>
  143. action is necessary to define attributes and to  compile  the  actions
  144. found  elsewhere;  for  this section, we will ignore its significance.
  145. The second action gives a main program that specifies where  C  is  to
  146. begin  execution.  It contains one statement which asks ANTLR to begin
  147. parsing at rule a.  The third instruction defines a token hello.   The
  148. fourth  component  of  this  description  is a rule definition.  Rules
  149. definitions have the form:
  150.  
  151.  
  152. rule: alternative  | alternative  | ... | alternative  ;
  153.                  1              2                    n
  154.  
  155.  
  156. where each alternative is a sequence of  grammatical  structures  that
  157. are  to be matched-one of possible structures is a simple token refer-
  158. ence (WORD, in our case).  Therefore, rule a says,  "match  the  token
  159. identified as WORD on the input stream".  The C function generated for
  160. rule a asks the lexical analyzer, generated by PCCTS, to collect char-
  161. acters  until  it sees a complete token.  Each token in the vocabulary
  162. is given a unique number which the lexical analyzer returns  to  indi-
  163. cate what token was just matched.  Function a() then verifies that the
  164. number  associated  with  WORD  is  indeed  returned  by  the  lexical
  165. analyzer.
  166.  
  167.      The above example can be tested via  the  following  sequence  of
  168. commands:
  169.  
  170.  
  171. antlr -gk t.g
  172. dlg -i parser.dlg scan.c
  173. cc -I../h -o t t.c scan.c err.c
  174.  
  175.  
  176. The first command generates the parser, t.c, the lexical  description,
  177. parser.dlg,  and  a  support file, err.c.  The second command converts
  178. the lexical description to a C file that constitutes our scanner (lex-
  179. ical analyzer).  The third command compiles all C files needed to gen-
  180. erate the executable (the -I../h option tells the C compiler where  to
  181. look  for  the  standard  PCCTS include files; you will have to change
  182.  
  183.  
  184.  
  185.                                                                 Page 3
  186.  
  187. PCCTS Introductory Tutorial 1.0x
  188.  
  189.  
  190. this to where the PCCTS include files are located).  The output on our
  191. UNIX system looks like this (assuming the example is in file t.g):
  192.  
  193.  
  194. % antlr -gk t.g
  195. Antlr parser generator   Version 1.06   1989-1992
  196. % dlg -i parser.dlg scan.c
  197. dlg  Version 1.0   1989, 1990, 1991
  198. % cc -I../h -o t t.c scan.c err.c
  199.  
  200.  
  201.  
  202. To test the grammar file, run the executable:
  203.  
  204.  
  205. % t
  206. hello
  207. %
  208.  
  209.  
  210.  
  211. No error message is generated and t  terminates  successfully.   If  a
  212. token not in the vocabulary of our language is typed, an error message
  213. appears.  We have only one word in our vocabulary, and hence, anything
  214. other than "hello, world" generates an error.
  215.  
  216.  
  217. % t
  218. bob
  219. invalid token near line 1 (text was 'b')
  220. invalid token near line 1 (text was 'o')
  221. invalid token near line 1 (text was 'b')
  222. invalid token near line 1 (text was '
  223. ^Dline 1: syntax error at "EOF" missing WORD
  224. %
  225.  
  226.  
  227.  
  228. The first "invalid token" errors are from the scanner, the  last  mes-
  229. sage is from the parser (function a()) indicating that end-of-file was
  230. found when a WORD was expected.   EOF  was  returned  by  the  scanner
  231. because  bob  was  ignored and end-of-file appeared immediately after-
  232. wards; EOF is a predefined token in any PCCTS vocabulary.
  233.  
  234.      Adding more tokens to your language's vocabulary  is  easy-simply
  235. add more #token definitions.  Consider this new example:
  236.  
  237.  
  238. #token    "\ "     <<zzskip();>>            /* ignore blanks */
  239. #token    "\t"     <<zzskip();>>            /* ignore tabs */
  240. #token    "\n"     <<zzline++; zzskip();>>  /* ignore newlines */
  241. #token A  "apple"
  242. #token P  "pear"
  243.  
  244.  
  245.  
  246.  
  247.                                                                 Page 4
  248.  
  249. PCCTS Introductory Tutorial 1.0x
  250.  
  251.  
  252. This example introduces lexical actions-actions that are executed upon
  253. recognition  of  a  particular  regular expression.  For most language
  254. descriptions, lexical actions are not used except to tell the  scanner
  255. to  skip a token or continue looking for more characters.  zzskip() is
  256. a      standard      PCCTS      function       (generally,       PCCTS
  257. variables/functions/defines  are prefixed with zz to avoid name colli-
  258. sions with user variables) which forces  the  scanner  to  ignore  the
  259. currently  matched token and to try to find another.  Essentially, the
  260. first three token definitions here tell the  scanner  that  it  is  to
  261. ignore  white  space, but to increment the current line number when it
  262. sees a newline.  The fourth and fifth definitions introduce two  words
  263. into  our vocabulary.  Notice that only the last two have labels asso-
  264. ciated with them.  Any #token instruction may give a label,  but  they
  265. are  not necessary.  Labels are handy when you want an action to refer
  266. to the value (token number) of a particular token; also, when a  regu-
  267. lar  expression is complicated or confusing, often it is better to use
  268. a label throughout your grammar  rather  than  repeating  the  regular
  269. expression.   To  illustrate  this,  we  present  the  following  four
  270. equivalent partial PCCTS descriptions:
  271.  
  272. (i)  Repeated use of labels.
  273.  
  274.  
  275. #token A "apple"
  276. #token P "pear"
  277.  
  278. a : A P
  279.   | P A
  280.   ;
  281.  
  282.  
  283.  
  284. (ii) Repeated use of expressions.
  285.  
  286.  
  287. #token "apple"
  288. #token "pear"
  289.  
  290. a : "apple" "pear"
  291.   | "pear" "apple"
  292.   ;
  293.  
  294.  
  295.  
  296. (iii)Repeated use of implicitly-defined expressions.
  297.  
  298.  
  299. a : "apple" "pear"
  300.   | "pear" "apple"
  301.   ;
  302.  
  303.  
  304.  
  305. (iv) Mixed use of labels and expressions.
  306.  
  307.  
  308.  
  309.                                                                 Page 5
  310.  
  311. PCCTS Introductory Tutorial 1.0x
  312.  
  313.  
  314.  
  315. #token A  "apple"
  316. #token P  "pear"
  317.  
  318. a : "apple" P
  319.   | "pear" A
  320.   ;
  321.  
  322.  
  323.  
  324. Each unique token regular-expression string  in  PCCTS  gets  its  own
  325. token  number.   Token  labels  are  words that begin with a uppercase
  326. letter whereas rules begin with lowercase letters.  Repeating the same
  327. token string in a grammar merely refers to the same token; strings can
  328. only appear once in #token definitions, however, as  this  instruction
  329. attempts  to  define  a new token.  An implicitly-defined token is one
  330. that is referenced but that has  no  formal  #token  instruction.   In
  331. fact, we use the #token only when the expression is long, when a lexi-
  332. cal action must be attached, or when a label is required (so that a  C
  333. action can refer to it).
  334.  
  335.      Each rule a above indicates that either apple followed by pear is
  336. to be matched or pear followed by apple is to be matched.
  337.  
  338.      Once again, let's test this vocabulary description  with  a  com-
  339. plete, executable example:
  340.  
  341.  
  342. #header <<#include "charbuf.h">>
  343.  
  344. <<main() { ANTLR(a(), stdin); }>>
  345.  
  346. #token    "\ "     <<zzskip();>>            /* ignore blanks */
  347. #token    "\t"     <<zzskip();>>            /* ignore tabs */
  348. #token    "\n"     <<zzline++; zzskip();>>  /* ignore newlines */
  349.  
  350. a : "apple" "pear"
  351.   | "pear" "apple"
  352.   ;
  353.  
  354.  
  355.  
  356. To build the executable, we proceed as before:
  357.  
  358.  
  359. % antlr -gk t.g
  360. Antlr parser generator   Version 1.06   1989-1992
  361. % dlg -i parser.dlg scan.c
  362. dlg  Version 1.0   1989, 1990, 1991
  363. % cc -g -I../h -o t t.c scan.c err.c
  364.  
  365.  
  366.  
  367. To test the example, type:
  368.  
  369.  
  370.  
  371.                                                                 Page 6
  372.  
  373. PCCTS Introductory Tutorial 1.0x
  374.  
  375.  
  376.  
  377. % t
  378. apple
  379.      pear
  380. %
  381.  
  382.  
  383. No error is reported due to the validity of the input.  Note that  the
  384. newline  and  the  spaces were ignored because of the zzskip() actions
  385. associated with our token definitions for white space.  To ensure that
  386. t is actually doing something useful, try:
  387.  
  388.  
  389. % t
  390. apple apple
  391. line 2: syntax error at "apple" missing pear
  392. ^D%
  393.  
  394.  
  395.  
  396. PCCTS generates parsers that automatically report errors  and  try  to
  397. resynchronize  the  parser;  hence,  in this case, a control-D (^D) is
  398. necessary to terminate the program because t is  looking  for  another
  399. token  with which to resynchronize.  Because of the zzline++ statement
  400. in the action for newline, the error is correctly reported on line 2.
  401.  
  402.      The regular expressions used in the above examples are simple and
  403. do not use any of the meta-characters or regular expression operators.
  404. Before presenting a more realistic example, we illustrate the  use  of
  405. some   useful  regular  expression  meta-characters  (for  a  complete
  406. description see PCCTS documentation):
  407.  
  408. @    EOF character
  409.  
  410. \t   tab character
  411.  
  412. \n   newline character
  413.  
  414. \c   character escape; used  to  obtain  actual  character  for  meta-
  415.      characters
  416.  
  417. (e)  keep expression e as an indivisible group
  418.  
  419. [c]  match one character from list c
  420.  
  421. [x-y]match one character from range x to y
  422.  
  423. ~[c] match one character not in list c
  424.  
  425. {e}  expression e is optional
  426.  
  427. e*   match zero or more of e
  428.  
  429. e+   match one or more of e
  430.  
  431.  
  432.  
  433.                                                                 Page 7
  434.  
  435. PCCTS Introductory Tutorial 1.0x
  436.  
  437.  
  438. e|f  match either expression e or f
  439.  
  440. Naturally, the above operators and meta-characters can be used in many
  441. combinations  to  produce very complicated expressions.  To illustrate
  442. more complex expressions, we define the  vocabulary  of  a  calculator
  443. (ignoring white space for the moment).
  444.  
  445.  
  446. #token NUM "[0-9]+"
  447. #token VAR "[a-zA-Z][a-zA-Z0-9]*"
  448. #token     "\("
  449. #token     "\)"
  450. #token     "\+"
  451. #token     "\-"
  452. #token     "\*"
  453. #token     "/"
  454.  
  455.  
  456.  
  457. A number is defined as a sequence  of  one  or  more  decimal  digits.
  458. Variables  begin  with an upper or lowercase letter, but can otherwise
  459. contain digits as well; note that * is used rather than  +  for  vari-
  460. ables  because + would force VAR to recognize at least two characters.
  461. This calculator has some tokens in its vocabulary that  are  identical
  462. to  those of the regular expressions, so these must be escaped to tell
  463. the scanner to look for those actual characters.  To create an execut-
  464. able,  we form a grammar which accepts one of the words in the vocabu-
  465. lary:
  466.  
  467.  
  468. #header <<#include "charbuf.h">>
  469.  
  470. <<main() { ANTLR(a(), stdin); }>>
  471.  
  472. #token     "\ "     <<zzskip();>>            /* ignore blanks */
  473. #token     "\t"     <<zzskip();>>            /* ignore tabs */
  474. #token     "\n"     <<zzline++; zzskip();>>  /* ignore newlines */
  475.  
  476.  
  477.  
  478.  
  479. #token NUM "[0-9]+"
  480. #token VAR "[a-zA-Z][a-zA-Z0-9]*"
  481. #token     "\("
  482. #token     "\)"
  483. #token     "\+"
  484. #token     "\-"
  485. #token     "\*"
  486. #token     "/"
  487.  
  488. a : NUM | VAR | "\(" | "\)" | "\+" | "\-" | "\*" | "/" ;
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.                                                                 Page 8
  496.  
  497. PCCTS Introductory Tutorial 1.0x
  498.  
  499.  
  500. As before, we create the executable with (assuming the example  is  in
  501. t.g):
  502.  
  503.  
  504. antlr -gk t.g
  505. dlg -i parser.dlg scan.c
  506. cc -g -I../h -o t t.c scan.c err.c
  507.  
  508.  
  509.  
  510. The executable, t, will recognize any one token from  our  vocabulary.
  511. The  next  section  discusses  how one employs rules to specify valid,
  512. structured sequences; i.e. how one defines the syntax of a language.
  513.  
  514. 3.  Syntactic Analysis
  515.  
  516.      The syntax of a language is the grammatical structure which  sum-
  517. marizes the set of valid phrases in that language.  Because one cannot
  518. normally delineate all possible sentences, languages are described via
  519. a  set  of  rules  which  obey  the  laws of a meta-language, which is
  520. literally a "language to describe languages" just  as  the  syntax  of
  521. regular expressions represents a language.  This section describes the
  522. format of a PCCTS language description-the syntax of PCCTS  rules  and
  523. how  they  may  be  used  to impose a structure upon a stream of input
  524. tokens.
  525.  
  526.      The basic template used to build a grammar is:
  527.  
  528.         #header action
  529.         action(s) and/or #token definition(s)
  530.         rule(s)
  531.         action(s) and/or #token definition(s)
  532.  
  533. To compile, all grammars must define a number  of  things  inside  the
  534. #header action; this instruction is not optional and must appear first
  535. in your file.  The rest of the file is basically a  sequence  of  user
  536. actions, token and rule definitions-except that actions, not contained
  537. within rules, must be placed before or after the rule definitions.
  538.  
  539.      Rules have the basic form:
  540.  
  541.  
  542. rule: alternative  | alternative  | ... | alternative  ;
  543.                  1              2                    n
  544.  
  545.  
  546. where alternative  is a sequence of the following elements:
  547.                  i
  548. token
  549.      Match token on the input stream.
  550.  
  551. rule  Visit rule and match whatever is specified.
  552.  
  553. action
  554.  
  555.  
  556.  
  557.                                                                 Page 9
  558.  
  559. PCCTS Introductory Tutorial 1.0x
  560.  
  561.  
  562.      Execute C action.
  563.  
  564. (a  | a  | ... | a )
  565.   1  Introduce a subrule-match one a .
  566.                                     i
  567. {a  | a  | ... | a }
  568.   1  Introduce an optional subrule; match one a  or none.
  569.                                                i
  570. (a  | a  | ... | a )*
  571.   1  Conditionallynmatch any sequence of a 's.
  572.                                           i
  573. (a  | a  | ... | a )+
  574.   1  Match any sequence of a 's.
  575.                             i
  576. Examples of rule definitions are:
  577.  
  578.  
  579. w   :   WORD ("," WORD)*
  580.     ;
  581.  
  582.  
  583.  
  584. where rule w matches a  list  of  comma-separated  WORD's.   The  (","
  585. WORD)*  construction says match zero or more "," WORD sequences.  Con-
  586. sider,
  587.  
  588.  
  589. st  :   "if" expr "then" st {"else" st} ";"
  590.     |   WORD ":=" expr
  591.     |   "begin" ( st ";" )+ "end"
  592.         ;
  593.  
  594.  
  595.  
  596. where expr is some rule that matches an arithmetic  expression.   Rule
  597. st matches statements such as:
  598.  
  599.  
  600. if expr  then begin
  601.   i := expr ;
  602.   j := expr2;
  603. end        3
  604. else
  605.   k := expr ;
  606.            4
  607.  
  608.  
  609. The first alternative has an optional subrule that  matches  an  else-
  610. clause  if  it  exists.   The  third  alternative  matches one or more
  611. semicolon-delimited statements, which are enclosed in begin  and  end.
  612. Let's examine the description of a simple expression.
  613.  
  614.  
  615.  
  616.  
  617.  
  618.  
  619.                                                                Page 10
  620.  
  621. PCCTS Introductory Tutorial 1.0x
  622.  
  623.  
  624.  
  625. e   :   e1 ( ("\+" | "\-") e1 )*
  626.     ;
  627.  
  628. e1  :   WORD
  629.     |   INT
  630.     ;
  631.  
  632.  
  633.  
  634. Rule e matches simple expressions with only plus and minus  as  opera-
  635. tors;  e.g.  a+3-b  or  a.  Note that we have nested the ("\+" | "\-")
  636. subrule within the (...)* subrule.
  637.  
  638.      Let's build a complete PCCTS language  description  by  extending
  639. the  expression  example.  Rules to handle multiplication and division
  640. will be added as well as  token  definitions  to  ignore  white  space
  641. etc...:
  642.  
  643.  
  644. #header <<#include "charbuf.h">>
  645.  
  646. <<main() { ANTLR(calc(), stdin); }>>
  647.  
  648. #token     "[\ \t]"  <<zzskip();>>           /* ignore blanks, tabs */
  649. #token     "\n"      <<zzline++;>>           /* ignore newlines */
  650. #token INT "[0-9]+"
  651. #token FLOAT "[0-9]+ {. [0-9]+}"
  652.  
  653. calc:   ( e "\n" )* "@"
  654.     ;
  655.  
  656. e   :   e1 ( ("\+" | "\-") e1 )*
  657.     ;
  658.  
  659. e1  :   e2 ( ("\*" | "/") e2 )*
  660.     ;
  661.  
  662. e2  :   INT
  663.         |       FLOAT
  664.     ;
  665.  
  666.  
  667.  
  668. Note that newlines are no longer to be ignored,  hence,  the  zzskip()
  669. function  call has been removed from its lexical action.  Our language
  670. is a set of expressions terminated by newlines followed by end-of-file
  671. (@  is  a  predefined  lexical  meta-symbol referring to end-of-file).
  672. Without actions, testing this grammar is uninteresting because no out-
  673. put  is generated (unless, of course, an invalid expression is given).
  674. Therefore, let us place an action among the rule elements to  generate
  675. some output.  Augment rule calc as follows:
  676.  
  677.  
  678.  
  679.  
  680.  
  681.                                                                Page 11
  682.  
  683. PCCTS Introductory Tutorial 1.0x
  684.  
  685.  
  686.  
  687. calc:   ( e "\n" <<printf("found expression\n");>> )* "@"
  688.     ;
  689.  
  690.  
  691.  
  692. Essentially, we have added C code to print out a brief  message  after
  693. an  expression-newline  pair has been encountered.  Create the execut-
  694. able, t, as before with:
  695.  
  696.  
  697. antlr -gk t.g
  698. dlg -i parser.dlg scan.c
  699. cc -I../h -o t t.c scan.c err.c
  700.  
  701.  
  702.  
  703.  
  704. Test the program via a few simple expressions:
  705.  
  706.  
  707. % t
  708. 3+4*5
  709. found expression
  710. 3.15 / 6 - 2.1
  711. found expression
  712. ^D%
  713.  
  714.  
  715.  
  716. This example grammar is not recursive; i.e. no rule references another
  717. rule that directly or indirectly returns to itself.  But, recursion is
  718. a very powerful tool.  It allows the concept of  self-similarity.   In
  719. other words, structures in which some subcomponents are similar to the
  720. outer structure.  Pascal has several self-similar  constructs:  record
  721. field definitions, procedure definitions, expressions, and type defin-
  722. itions to name a few.
  723.  
  724.      To illustrate recursive grammars, we extend the above  expression
  725. example to allow parenthesized subexpressions such as (3+4)*7.
  726.  
  727.  
  728. e2  :   INT
  729.         |       FLOAT
  730.     |   "\(" e "\)"
  731.     ;
  732.  
  733.  
  734.  
  735. Placing the subexpression construct  at  the  lowest  recursion  level
  736. makes  it  have  the  highest precedence because of the nature of top-
  737. down, depth-first parsing.  To see this, consider the parse  tree  for
  738. (3+4)*5 (beginning at rule e):
  739.  
  740.  
  741.  
  742.  
  743.                                                                Page 12
  744.  
  745. PCCTS Introductory Tutorial 1.0x
  746.  
  747.  
  748.  
  749. [Figure omitted]
  750.  
  751. Clearly, 3+4 must be evaluated before the * for a valid  result;  this
  752. is  precisely  a depth-first evaluation of the parse tree (which PCCTS
  753. parsers do naturally).  The deeper the recursive nesting,  the  higher
  754. the precedence.  Extending the input expression to (3+4)*(5-6) yields:
  755.  
  756. [Figure omitted]
  757.  
  758. Again, both operands of the * must be evaluated before it can proceed.
  759.  
  760.      As another example of recursive definitions, consider type defin-
  761. itions for a Pascal-like language.  Types look like:
  762.  
  763.  
  764. char
  765. integer
  766. array [5] of char
  767. array [100] of array [20] of integer
  768.  
  769.  
  770.  
  771. A grammar similar to the following could be used:
  772.  
  773.  
  774. type:   "char"
  775.     |   "integer"
  776.     |   "array" "\[" INT "\]" "of" type
  777.     ;
  778.  
  779.  
  780. The recursive invocation of type by the array alternative  effectively
  781. allows chains of array specifications.  The parse tree for
  782.  
  783.  
  784. array [100] of array [20] of integer
  785.  
  786.  
  787.  
  788. looks like:
  789.  
  790. [Figure omitted]
  791.  
  792. In this case, we are less interested in precedence and more interested
  793. in allowing chains of array specifications.
  794.  
  795.      In general, recursion and repetition constructs  such  as  (...)+
  796. are  needed  to  avoid delineating all possible phrases in a language.
  797. Grammars are descriptions of the patterns found among the phrases of a
  798. particular language just as R notation summarizes an infinite series.
  799.  
  800.      The recognition of input languages, via the use of grammars, per-
  801. forms two tasks: it ensures phrase validity and directs translation to
  802.  
  803.  
  804.  
  805.                                                                Page 13
  806.  
  807. PCCTS Introductory Tutorial 1.0x
  808.  
  809.  
  810. an output language.  The next section demonstrates how actions, embed-
  811. ded among the grammar elements, can be used to effect a translation.
  812.  
  813. 4.  Translation
  814.  
  815.      Given a grammar, PCCTS constructs a  recognizer  for  phrases  in
  816. that  input  language.   No  translation  from input to output is per-
  817. formed.  User actions must be supplied in  the  correct  positions  to
  818. generate  output.   Translation  occurs when an action produces output
  819. which is a function of the input phrase.  Actions have access to input
  820. phrase token values through an abstraction called an attribute.  These
  821. attributes are user-defined types and can be as  simple  as  the  text
  822. associated with a token.
  823.  
  824.      This section introduces the notion of an attribute as a means  of
  825. communicating with the lexical analyzer and presents a number of exam-
  826. ples that explain how and where actions can be used to  generate  out-
  827. put.
  828.  
  829. 4.1.  Attributes
  830.  
  831.      Attributes are objects associated with all rules  and  rule  ele-
  832. ments, but we will only concern ourselves here with attributes associ-
  833. ated with token and rule references.   Attributes  are  referenced  in
  834. actions  with the notation $i where i indicates that the attribute for
  835. the ith token in that production is desired.  Attributes are  run-time
  836. objects  and have no value until run-time.  They are generally used to
  837. access the actual text (or a function  of  the  text)  of  the  tokens
  838. matched  on the input stream.  The set of all tokens defines the voca-
  839. bulary of the input language.  The term "token" collectively refers to
  840. the  token  type (an integer that identifies it as part of the vocabu-
  841. lary) and the token text (the actual string that matched  the  regular
  842. expression for the token type).
  843.  
  844.      Before illustrating attributes, we begin with  an  example.   The
  845. vocabulary  of  an  input  language  (known a priori) may be the set {
  846. WORD, "begin", INT }, which is the set of integer  token  types.   The
  847. text  associated  with  a  token type is only known at parser run-time
  848. because it depends on the input characters.  Let us say that the gram-
  849. matical  structure  of  the  language is any sequence of tokens in the
  850. vocabulary (ignoring white space); then, a valid sentence could be:
  851.  
  852.  
  853. begin hello 34 13 bob
  854.  
  855.  
  856.  
  857. The parser would see a token stream of tuples of the form (token type,
  858. token text):
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.                                                                Page 14
  868.  
  869. PCCTS Introductory Tutorial 1.0x
  870.  
  871.  
  872.  
  873. (begin, begin)
  874. (WORD, hello)
  875. (INT, 34)
  876. (INT, 13)
  877. (WORD, bob)
  878.  
  879.  
  880.  
  881. A different input sentence, with the same sequence of token types is:
  882.  
  883.  
  884. begin hi 2 99 ptr
  885.  
  886.  
  887.  
  888. which would yield the same sequence of token types,  but  a  different
  889. set of token text:
  890.  
  891.  
  892. (begin, begin)
  893. (WORD, hi)
  894. (INT, 2)
  895. (INT, 99)
  896. (WORD, ford)
  897.  
  898.  
  899. The grammar might look like:
  900.  
  901.  
  902. a : ( WORD | "begin" | INT )+
  903.   ;
  904.  
  905.  
  906.  
  907. Only the token types are referenced in the grammar  as  they  describe
  908. the structure of the language and are a shorthand notation for the set
  909. of valid input sentences.  Obviously, one could not delineate all pos-
  910. sible sentences as there are infinitely many.  For a PCCTS description
  911. to perform a translation that is specific  to  the  particular  input,
  912. actions  must  access the text of the input tokens, not just the token
  913. type.  Attributes are provided to provide access to the text (or  some
  914. function  thereof)  of  an input token.  To illustrate this, we give a
  915. complete example and then, later, describe the particulars:
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.                                                                Page 15
  930.  
  931. PCCTS Introductory Tutorial 1.0x
  932.  
  933.  
  934.  
  935. #header <<#include "charptr.h">>
  936.  
  937. <<main() { ANTLR(a(), stdin); }>>
  938.  
  939. #token "[\ \t]"        <<zzskip();>>
  940. #token "\n"            <<zzline++; zzskip();>>
  941.  
  942. a : ( WORD    <<printf(" %s", $1);>>
  943.     | "begin" <<printf(" begin");>>
  944.     | INT     <<printf(" %s", $1);>>
  945.     )+
  946.   ;
  947.  
  948. #token WORD "[a-z]+"
  949. #token INT  "[0-9]+"
  950.  
  951.  
  952.  
  953. This example defines attributes to be strings  representing  what  was
  954. found  on  the  input stream and prints the stream of tokens back out.
  955. In other words, attributes are merely a copy of the words  found;  the
  956. mapping  from  token/lexeme  to  attribute  is an identity mapping (do
  957. nothing but copy).  For the moment, concentrate on  the  actions.   $1
  958. refers  to  the attribute of the first item in the production in which
  959. the action occurs; in this case, only one item appears per production.
  960. Note  that  the action for the "begin" token does not need to refer to
  961. its attribute as it will always be begin.  The rest  of  this  section
  962. describes  the particulars needed to understand everything else in the
  963. example.
  964.  
  965.      PCCTS requires that the user define the data type or structure of
  966. the  attributes  as  well  as  specify  how to convert from lexemes to
  967. attributes.  The type is always defined by a C  typedef  named  Attrib
  968. and must be defined in the action associated with the #header instruc-
  969. tion.  For example, if one wishes the attribute for a token to be sim-
  970. ple integers, the following is a sufficient type definition:
  971.  
  972.  
  973. #header <<typedef int Attrib;>>
  974.  
  975.  
  976.  
  977. However, this does not tell PCCTS how to convert a token to an  attri-
  978. bute.   This  is accomplished with a function called zzcr_attr() which
  979. defines the value of an attribute given complete information  about  a
  980. lexeme (token number and associated text).  It has the general form:
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.                                                                Page 16
  992.  
  993. PCCTS Introductory Tutorial 1.0x
  994.  
  995.  
  996.  
  997. void
  998. zzcr_attr(a,token,text)
  999. Attrib *a;
  1000. int token;
  1001. char *text;
  1002. {
  1003.     /* *a = function(token, text); */
  1004. }
  1005.  
  1006.  
  1007. where a points to an attribute created by PCCTS at run-time.  The user
  1008. simply  has to assign a value to *a.  In our case, we will use a macro
  1009. version to set our attributes to the integer value of the input:
  1010.  
  1011.  
  1012. #define zzcr_attr(a,tok,txt) {*(a) = atoi(txt);}
  1013.  
  1014.  
  1015.  
  1016. This specifies that whenever a token is matched on the input stream by
  1017. the parser, an attribute of type int is to be created and assigned the
  1018. result of atoi(text) where text is the character  string  matched  for
  1019. the  token.   The attribute is then made available as $i to actions in
  1020. the production that matched the token.  For example,
  1021.  
  1022.  
  1023. #header <<
  1024.     typedef int Attrib;
  1025.     #define zzcr_attr(a,tok,txt) {*(a) = atoi(txt);}
  1026. >>
  1027.  
  1028. <<main() { ANTLR(a(), stdin); }>>
  1029.  
  1030. #token "[\ \t]"        <<zzskip();>>
  1031. #token "\n"            <<zzline++; zzskip();>>
  1032.  
  1033. a   :   "hi" "[0-9]+" <<printf("$1, $2 are %d, %d\n", $1, $2);>>
  1034.     ;
  1035.  
  1036.  
  1037.  
  1038. $1 refers to the first token in the alternative, "hi";  similarly,  $2
  1039. refers  to the the second token, "[0-9]+".  When executed, the execut-
  1040. able t (created as before) yields:
  1041.  
  1042.  
  1043. % t
  1044. hi 34
  1045. $1, $2 are 0, 34
  1046. %
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.                                                                Page 17
  1054.  
  1055. PCCTS Introductory Tutorial 1.0x
  1056.  
  1057.  
  1058. where atoi() of a non-numeric string is 0, but the text 34  gets  con-
  1059. verted  to an integer (binary word) version of 34 and printed back out
  1060. as a number.
  1061.  
  1062.      The token type can be tested to ensure  that  it  is  an  integer
  1063. before applying the atoi() function via:
  1064.  
  1065.  
  1066. #header <<
  1067.     typedef int Attrib;
  1068.     #define zzcr_attr(a,tok,txt) {if ( tok==INT ) *(a) = atoi(txt);}
  1069. >>
  1070.  
  1071.  
  1072.  
  1073. where INT is defined to be "[0-9]+".  This defines  an  attribute  for
  1074. all INT tokens found on the input stream.  Other tokens have undefined
  1075. attributes.
  1076.  
  1077.      Attributes can have multiple  elements  or  assume  one  of  many
  1078. values.   For example, we can extend the above example to handle FLOAT
  1079. tokens as well:
  1080.  
  1081.  
  1082. #header <<typedef union { int ival; float fval; } Attrib;>>
  1083.  
  1084.  
  1085.  
  1086.  
  1087. <<
  1088. void
  1089. zzcr_attr(a,token,text)
  1090. Attrib *a;
  1091. int token;
  1092. char *text;
  1093. {
  1094.     switch ( token )
  1095.     {
  1096.         case INT   : (a)->ival = atoi(text); break;
  1097.         case FLOAT : (a)->fval = atof(text); break;
  1098.     }
  1099. }
  1100. >>
  1101.  
  1102.  
  1103.  
  1104. The typedef specifies that attributes are integer  or  floating  point
  1105. values.   When  the  regular  expression  for  a floating point number
  1106. (integer number) is matched on the input stream, zzcr_attr()  converts
  1107. the string of characters representing that number to a C float (int).
  1108.  
  1109.      Attributes can  become  even  more  complicated,  but  typically,
  1110. attributes are merely a copy of the text found on the input stream.  A
  1111. standard PCCTS attribute definition is available as charbuf.h  and  is
  1112.  
  1113.  
  1114.  
  1115.                                                                Page 18
  1116.  
  1117. PCCTS Introductory Tutorial 1.0x
  1118.  
  1119.  
  1120. defined as follows:
  1121.  
  1122.  
  1123. /* PCCTS attribute -- constant width text */
  1124. #ifndef D_TextSize
  1125. #define D_TextSize      30
  1126. #endif
  1127.  
  1128. typedef struct { char text[D_TextSize]; } Attrib;
  1129.  
  1130. #define zzcr_attr(a,tok,t)      strncpy((a)->text, t, D_TextSize-1);
  1131.  
  1132.  
  1133.  
  1134. These attributes are referred to by $i.text in actions.
  1135.  
  1136.      Each alternative begins a  new  sequence  of  $i's  and  from  an
  1137. enclosing  scope/level,  entire subules are counted as one unit.  This
  1138. is best explained with an example:
  1139.  
  1140.  
  1141. a   :   A B ( C D )+ E
  1142.     |   F G
  1143.     ;
  1144.  
  1145.  
  1146.  
  1147. From an action after token E, A is $1, B is $2, the entire subrule ( C
  1148. D  )  is  $3,  and  E is $4; C and D are inaccessible from outside the
  1149. scope of the subrule.  From an action inside the  subrule  just  after
  1150. the  token  D, C is $1 and D is $2.  In alternative two from an action
  1151. after G, F is $1 and F is $2.  Attributes have  a  scoping  just  like
  1152. variables in a programming langauage.
  1153.  
  1154.      Attributes  are  a  means  of  communicating  with  the   lexical
  1155. analyzer.   Actions may use these attributes to provide a translation.
  1156. The next section utilizes the concepts presented here to build  trans-
  1157. lators.
  1158.  
  1159. 4.2.  Actions
  1160.  
  1161.      Actions are rule elements just like token references, but perform
  1162. a  different  function.   Token  references indicate that a particular
  1163. token is to be matched on the input stream at that point in the parse.
  1164. Actions  indicate that this action is to be performed at that point in
  1165. the parse, immediately following the preceding token match.  For exam-
  1166. ple,
  1167.  
  1168.  
  1169. a   :   A <<action >> B ;
  1170.     |  ( C )+ <<action >>
  1171.     ;                 2
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.                                                                Page 19
  1178.  
  1179. PCCTS Introductory Tutorial 1.0x
  1180.  
  1181.  
  1182. action  is executed after the parser has found an A, but before it has
  1183. found 1a  B.  action  is executed only after a sequence of one or more
  1184. C's has been found. 2
  1185.  
  1186.      As a more concrete example, we augment the above calc example  to
  1187. print something more useful than found expression:
  1188.  
  1189.  
  1190. calc:   ( e "\n" <<printf("\n");>> )* "@"
  1191.     ;
  1192.  
  1193. e   :   e1
  1194.         (   (  "\+" <<printf(" add");>>
  1195.             |  "\-" <<printf(" sub");>>
  1196.             )
  1197.             e1
  1198.         )*
  1199.     ;
  1200.  
  1201.  
  1202.  
  1203.  
  1204. e1  :   e2
  1205.         (   (  "\*" <<printf(" mult");>>
  1206.             |  "/"   <<printf(" div");>>
  1207.             )
  1208.             e2
  1209.         )*
  1210.     ;
  1211.  
  1212. e2  :   INT     <<printf(" INT");>>
  1213.         |       FLOAT   <<printf(" FLOAT");>>
  1214.     ;
  1215.  
  1216.  
  1217.  
  1218. Essentially, we have added C code to print out the operand  types  and
  1219. operators.  Create the executable, t, as before with
  1220.  
  1221.  
  1222. antlr -gk t.g
  1223. dlg -i parser.dlg scan.c
  1224. cc -I../h -o t t.c scan.c err.c
  1225.  
  1226.  
  1227.  
  1228. Test the program via a few simple expressions:
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.                                                                Page 20
  1240.  
  1241. PCCTS Introductory Tutorial 1.0x
  1242.  
  1243.  
  1244.  
  1245. % t
  1246. 3+4*5
  1247.  INT add INT mult INT
  1248. 3.15 / 6 - 2.1
  1249.  FLOAT div INT sub FLOAT
  1250. ^D%
  1251.  
  1252.  
  1253.  
  1254. Now, let's use the attributes to generate code for a  simple  reverse-
  1255. polish stack machine whose operations are defined as follows:
  1256.  
  1257. push opnd
  1258.      Push opnd onto the stack.
  1259.  
  1260. printPrint the value of the top of stack; POP the value off the stack.
  1261.  
  1262. add   PUSH(POP + POP)
  1263.  
  1264. sub   a := POP
  1265.      b := POP
  1266.      PUSH(b - a)
  1267.  
  1268. mult
  1269.      PUSH(POP * POP)
  1270.  
  1271. div   a := POP
  1272.      b := POP
  1273.      PUSH(b / a)
  1274.  
  1275. Modify the rules as follows:
  1276.  
  1277.  
  1278. #header <<#include "charbuf.h">>
  1279.  
  1280. <<main() { ANTLR(calc(), stdin); }>>
  1281.  
  1282. #token     "[\ \t]"  <<zzskip();>>           /* ignore blanks, tabs */
  1283. #token     "\n"      <<zzline++;>>           /* ignore newlines */
  1284. #token INT "[0-9]+"
  1285. #token FLOAT "[0-9]+ {. [0-9]+}"
  1286.  
  1287.  
  1288.  
  1289.  
  1290.  
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300.  
  1301.                                                                Page 21
  1302.  
  1303. PCCTS Introductory Tutorial 1.0x
  1304.  
  1305.  
  1306.  
  1307. calc:   ( e "\n" <<printf("\tprint\n");>> )* "@"
  1308.     ;
  1309.  
  1310. e   :   <<char *op;>>
  1311.         e1
  1312.         (   (  "\+" <<op="\tadd\n";>>
  1313.             |  "\-" <<op="\tsub\n";>>
  1314.             )
  1315.             e1
  1316.                         <<printf("%s", op);>>
  1317.         )*
  1318.     ;
  1319.  
  1320.  
  1321.  
  1322.  
  1323. e1  :   <<char *op;>>
  1324.         e2
  1325.         (   (  "\*"  <<op="\tmult\n";>>
  1326.             |  "/"   <<op="\tdiv\n";>>
  1327.             )
  1328.             e2
  1329.                         <<printf("%s", op);>>
  1330.         )*
  1331.     ;
  1332.  
  1333. e2  :   INT     <<printf("\tpush %s\n", $1.text);>>
  1334.         |       FLOAT   <<printf("\tpush %s\n", $1.text);>>
  1335.     ;
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.                                                                Page 22
  1364.  
  1365. PCCTS Introductory Tutorial 1.0x
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.                           Table of Contents
  1372.  
  1373.  
  1374.  
  1375.  
  1376. 1. Introduction .................................................    2
  1377.  
  1378. 2. Lexical Analysis .............................................    2
  1379.  
  1380. 3. Syntactic Analysis ...........................................    9
  1381.  
  1382. 4. Translation ..................................................   14
  1383.  
  1384.          4.1. Attributes ........................................   14
  1385.  
  1386.          4.2. Actions ...........................................   19
  1387.  
  1388.  
  1389.  
  1390.  
  1391.  
  1392.  
  1393.  
  1394.  
  1395.  
  1396.  
  1397.  
  1398.  
  1399.  
  1400.  
  1401.  
  1402.  
  1403.  
  1404.  
  1405.  
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411.  
  1412.  
  1413.  
  1414.  
  1415.  
  1416.  
  1417.  
  1418.  
  1419.  
  1420.  
  1421.  
  1422.  
  1423.  
  1424.  
  1425.  
  1426.  
  1427.